package com.heiye.blog.ai.servie.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heiye.blog.ai.constants.AIConstants;
import com.heiye.blog.ai.domain.dos.ChatDO;
import com.heiye.blog.ai.domain.dos.ChatMessageDO;
import com.heiye.blog.ai.domain.dos.RoleDO;
import com.heiye.blog.ai.domain.mapper.ChatMapper;
import com.heiye.blog.ai.domain.mapper.ChatMessageMapper;
import com.heiye.blog.ai.domain.mapper.RobotMapper;
import com.heiye.blog.ai.enums.ResponseCodeEnum;
import com.heiye.blog.ai.factory.TextModelStrategyFactory;
import com.heiye.blog.ai.model.dto.AIChatRequest;
import com.heiye.blog.ai.model.vo.*;
import com.heiye.blog.ai.servie.ChatService;
import com.heiye.blog.ai.strategy.text.TextModelStrategy;
import com.heiye.blog.framework.common.exception.BizException;
import com.heiye.blog.framework.common.response.Response;
import com.heiye.blog.framework.common.util.StringUtil;
import com.heiye.blog.framework.mybatis.response.PageResponse;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: heiye
 * @date: 2025/10/09 下午8:28
 * @version: v1.0.0
 * @description: 对话
 */
@Service
public class ChatServiceImpl implements ChatService {

    @Resource
    private ChatMapper chatMapper;

    @Resource
    private ChatMessageMapper chatMessageMapper;

    @Resource
    private RobotMapper robotMapper;

    @Resource
    private TextModelStrategyFactory textModelStrategyFactory;

    /**
     * 新建对话
     *
     * @param newChatReqVO
     * @return
     */
    @Override
    public Response<NewChatRspVO> newChat(NewChatReqVO newChatReqVO) {
        // TODO: 获取登录用户 ID
        Long userId = 1L;
        // 调用该接口默认使用系统 AI
        Long roleId = AIConstants.SYSTEM_AI_ID;
        // 用户发送的消息
        String message = newChatReqVO.getMessage();

        // 生成对话 UUID
        String uuid = UUID.randomUUID().toString();
        // 截取用户发送的消息，作为对话摘要
        String summary = StringUtil.truncate(message, 20);

        // 存储对话记录到数据库中
        chatMapper.insert(ChatDO.builder()
                .userId(userId)
                .roleId(roleId)
                .summary(summary)
                .uuid(uuid)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build());

        // 将摘要、UUID 返回给前端
        return Response.success(NewChatRspVO.builder()
                .roleId(roleId)
                .uuid(uuid)
                .summary(summary)
                .build());
    }

    /**
     * 流式对话
     *
     * @param aiChatReqVO
     * @return
     */
    @Override
    public Flux<AIResponse> chat(AiChatReqVO aiChatReqVO) {
        // 模型名称
        String modelName = aiChatReqVO.getModelName();
        // 获取文本模型策略
        TextModelStrategy strategy = textModelStrategyFactory.getStrategy(modelName);

        // 不支持的文本模型，返回错误信息
        if (Objects.isNull(strategy)) {
            return Flux.error(new BizException(ResponseCodeEnum.TEXT_MODEL_NOT_EXISTED));
        }

        // 创建 AIChatRequest 对象
        AIChatRequest aiChatRequest = new AIChatRequest(aiChatReqVO);

        // 调用文本模型策略，获取流式响应
        return strategy.handleStreamResponse(aiChatRequest);
    }

    /**
     * 查询历史消息
     *
     * @param findChatHistoryMessagePageListReqVO
     * @return
     */
    @Override
    public PageResponse<FindChatHistoryMessagePageListRspVO> findChatHistoryMessagePageList(FindChatHistoryMessagePageListReqVO findChatHistoryMessagePageListReqVO) {
        // 获取当前页、以及每页需要展示的数据量
        Long current = findChatHistoryMessagePageListReqVO.getCurrent();
        Long size = findChatHistoryMessagePageListReqVO.getSize();
        String chatId = findChatHistoryMessagePageListReqVO.getChatId();

        // 执行分页查询
        Page<ChatMessageDO> chatMessageDOPage = chatMessageMapper.selectPageList(current, size, chatId);

        List<ChatMessageDO> chatMessageDOS = chatMessageDOPage.getRecords();
        // DO 转 VO
        List<FindChatHistoryMessagePageListRspVO> vos = null;

        if (CollUtil.isNotEmpty(chatMessageDOS)) {
            vos = chatMessageDOS.stream()
                    .map(chatMessageDO -> FindChatHistoryMessagePageListRspVO.builder()
                            .id(chatMessageDO.getId())
                            .chatId(chatMessageDO.getChatUuid())
                            .content(chatMessageDO.getContent())
                            .role(chatMessageDO.getRole())
                            .createTime(chatMessageDO.getCreateTime())
                            .build())
                    // 升序排序
                    .sorted(Comparator.comparing(FindChatHistoryMessagePageListRspVO::getCreateTime))
                    .collect(Collectors.toList());
        }

        return PageResponse.success(chatMessageDOPage, vos);
    }

    /**
     * 查询历史对话
     *
     * @param findChatHistoryPageListReqVO
     * @return
     */
    @Override
    public PageResponse<FindChatHistoryPageListRspVO> findChatHistoryPageList(FindChatHistoryPageListReqVO findChatHistoryPageListReqVO) {
        // TODO：获取当前登录用户 ID
        Long userId = 1L;
        // 获取当前页、以及每页需要展示的数据数量
        Long current = findChatHistoryPageListReqVO.getCurrent();
        Long size = findChatHistoryPageListReqVO.getSize();

        // 执行分页查询
        Page<ChatDO> chatDOPage = chatMapper.selectPageList(current, size, userId);

        // 获取查询结果
        List<ChatDO> chatDOS = chatDOPage.getRecords();

        // 判断分页结果是否为空
        if (CollUtil.isEmpty(chatDOS)) {
            return PageResponse.success(chatDOPage, null);
        }

        // 获取智能体 ID
        List<Long> robotIds = chatDOS.stream()
                .map(ChatDO::getRoleId)
                // 去重
                .distinct()
                .toList();

        // 批量查询智能体信息
        List<RoleDO> roleDOS = robotMapper.selectByIds(robotIds);

        // 构建 Map, 方便后续获取智能体的信息
        Map<Long, RoleDO> roleDOMap = roleDOS.stream()
                .collect(Collectors.toMap(RoleDO::getId, Function.identity()));

        // DO 转 VO
        List<FindChatHistoryPageListRspVO> vos = null;
        if (CollUtil.isNotEmpty(chatDOS)) {
            vos = chatDOS.stream()
                    // 构建返参 VO
                    .map(chatDO -> {
                        // 获取智能体 ID
                        Long roleId = chatDO.getRoleId();

                        // 获取智能体信息
                        RoleDO robotDO = roleDOMap.get(roleId);

                        // 构建返回参数
                        if (Objects.nonNull(robotDO)) {
                            return FindChatHistoryPageListRspVO.builder()
                                    .id(chatDO.getId())
                                    .roleId(roleId)
                                    .uuid(chatDO.getUuid())
                                    .roleName(robotDO.getNickname())
                                    .roleAvatar(robotDO.getAvatar())
                                    .summary(chatDO.getSummary())
                                    .updateTime(chatDO.getUpdateTime())
                                    .build();
                        }
                        return null;
                    })
                    .collect(Collectors.toList());
        }

        return PageResponse.success(chatDOPage, vos);
    }

    /**
     * 重命名对话摘要
     *
     * @param renameChatReqVO
     * @return
     */
    @Override
    public Response<?> renameChatSummary(RenameChatReqVO renameChatReqVO) {
        // 对话 ID
        Long chatId = renameChatReqVO.getId();
        // 摘要
        String summary = renameChatReqVO.getSummary();

        // 根据主键 ID 更新摘要
        chatMapper.updateById(ChatDO.builder()
                .id(chatId)
                .summary(summary)
                .build());

        return Response.success();
    }

    /**
     * 删除对话
     *
     * @param deleteChatReqVO
     * @return
     */
    @Override
    public Response<?> deleteChat(DeleteChatReqVO deleteChatReqVO) {
        // 对话 UUID
        String chatUuid = deleteChatReqVO.getUuid();

        // 删除对话
        int count = chatMapper.delete(Wrappers.<ChatDO>lambdaQuery()
                .eq(ChatDO::getUuid, chatUuid));

        // 如果删除操作影响的行数为 0，说明想要删除的对话不存在
        if (count == 0) {
            throw new BizException(ResponseCodeEnum.CHAT_NOT_EXISTED);
        }

        // 批量删除对话下的所有消息
        chatMessageMapper.delete(Wrappers.<ChatMessageDO>lambdaQuery()
                .eq(ChatMessageDO::getChatUuid, chatUuid));

        return Response.success();
    }
}
